//**************************************************************
//		Controller.m
//			AppHider
//
//	Copyright (c) 2008 Metta Media
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//**************************************************************

#import "Controller.h"


@implementation Controller
-(id) init
{
	self = [super init];
	if (self != nil) {
		//read support folder
		//enumerate thru names
		
		//notification = [NSDistributedNotificationCenter defaultCenter];
		
		statusItems = [[[NSMutableArray alloc] init] retain];
		supportFolder = [MABSupportFolder sharedController];
		NSFileManager * fm = [NSFileManager defaultManager]; 
		NSString * currentPlist;
		BOOL isDirectory;
		
		NSString * exportedAppPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Applications"];
		if([fm fileExistsAtPath:exportedAppPath isDirectory:&isDirectory] && isDirectory && [fm directoryContentsAtPath:exportedAppPath] != nil)
		{
			exportedApp = YES;
			NSDictionary * contents;
			for (currentPlist in [fm directoryContentsAtPath:exportedAppPath])
			{
				NSString * path = [NSString stringWithFormat:@"%@/%@.plist", exportedAppPath, currentPlist, nil];
				if([fm fileExistsAtPath:path isDirectory:NO])
				{
					contents = [[NSDictionary alloc] initWithContentsOfFile:path];
					ApplicationMenu * theApp = [[ApplicationMenu alloc] initWithDictionary:contents];
					[statusItems addObject:theApp];
					[theApp release];
					[contents release];
					//[self savePrefs];
					NSLog(@"path is: %@", path);
				}
			}
		}
		
		else{	
			defaults = [NSUserDefaults standardUserDefaults];
			[defaults addSuiteNamed:@"com.mettamedia.AppHider"];
			appOrder = [[[NSMutableArray alloc] init] retain];
			[appOrder setArray:[defaults objectForKey:@"Application Order"]]; 
			appDir = [defaults objectForKey:@"Application Direction"];
		
			if([appOrder count] != 0)
			{
				NSString * directory = [supportFolder supportFolder];
				NSLog(@"dir = %@", directory);
				if ([fm fileExistsAtPath: directory isDirectory: &isDirectory] && isDirectory)
				{
					NSDictionary * contents;
					for (currentPlist in appOrder)
					{
						NSString * path = [NSString stringWithFormat:@"%@/%@.plist", directory, currentPlist, nil];
						NSLog(@"path = %@", path);
						if([fm fileExistsAtPath:path isDirectory:NO])
						{
							contents = [[NSDictionary alloc] initWithContentsOfFile:path];
							ApplicationMenu * theApp = [[ApplicationMenu alloc] initWithDictionary:contents];
							[statusItems addObject:theApp];
							[theApp release];
							[contents release];
							//[self savePrefs];
						}
					}
				}
			}
		}
	}
	return self;
}

- (void)dealloc
{
	[statusItems release];
	[super dealloc];
}

-(void)awakeFromNib
{
	/* [notification addObserver:self selector:@selector(addApplicationMenu:) name:@"AppHider_shouldAddApplicationMenu" object:nil];
		[notification addObserver:self selector:@selector(removeApplicationMenu:) name:@"AppHider_shouldRemoveApplicationMenu" object:nil];
		[notification addObserver:self selector:@selector(reorderMenus:) name:@"AppHider_shouldReorderMenus" object:nil];
		[notification addObserver:self selector:@selector(updateMenu:) name:@"AppHider_shouldUpdateApplicationMenu" object:nil]; */
	
	[self launchStatusItems];
}

-(void)launchStatusItems
{
	id currItem;
	NSStatusItem * statusItem;
	statusItemDict = [[NSMutableDictionary dictionary] retain];
	NSImage * icon;
	NSEnumerator * arayEnum = ([appDir isEqualToString:@"RL"]?[statusItems objectEnumerator]:[statusItems reverseObjectEnumerator]);
	for(currItem in arayEnum)
	{
		icon = [currItem icon];
		[icon setSize:NSMakeSize(16,16)];
		statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
		[statusItem setTitle:([[currItem itemTitle] isEqualToString:@""]?nil:[currItem itemTitle])];
		[statusItem setToolTip:([[currItem toolTip] isEqualToString:@""]?nil:[currItem toolTip])];//app name?
		[statusItem setHighlightMode:YES];
		[statusItem setImage:icon];
		if([currItem grayScale])[statusItem setAlternateImage:[self invertImage:icon]];
		NSMenu * menu = [self buildMenu:[currItem appItems]];
		if(exportedApp)
		{
			[menu addItem:[NSMenuItem separatorItem]];
			[menu addItemWithTitle:@"About" action:@selector(showAbout) keyEquivalent:@""];
			[menu addItemWithTitle:@"Website" action:@selector(showSite) keyEquivalent:@""];
			[statusItem setMenu:menu];
		}
		[statusItem setMenu:menu];
		[statusItemDict setObject:statusItem forKey:[currItem name]];
	}
}

-(void)releaseStatusItems
{
	[statusItemDict release];
}
	
-(NSMenu*)buildMenu:(NSArray*)arr
{
	NSMenu * newMenu = [[NSMenu alloc] init];
	id currItem;
	NSMenuItem *item;
	
	for (currItem in arr) {
		if([[currItem itemAction] isEqualTo:@"Keystroke"])
		{
			item = [[[NSMenuItem alloc] initWithTitle:[currItem itemName] action:@selector(click:) keyEquivalent:@""] retain];
			NSDictionary * itemPrefs = [[NSDictionary dictionaryWithDictionary:[currItem returnItemPreferences]] retain];
			//NSArray * objects = [[NSArray arrayWithObjects:[currItem itemValue], [itemPrefs objectForKey:@"modifier"], [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:identifier], nil] retain];
			[item setRepresentedObject:currItem];
			[item setTarget:self];
			[newMenu addItem:item];
			[item release];
			//[objects release];
			[itemPrefs release];
			//[newMenu addItem:[[AHMenuItem alloc] initWithTitle:[currItem itemName] action:@"runKeystroke" withObjects:[NSArray arrayWithObjects:[currItem itemValue], [NSArray arrayWithObjects:[[currItem returnItemPreferences] objectForKey:@"modifier"], [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:identifier],nil], nil] keyEquivalent:nil target:self]];
		}
		if([[currItem itemAction] isEqualTo:@"Applescript"])
		{
			item = [[[NSMenuItem alloc] initWithTitle:[currItem itemName] action:@selector(click:) keyEquivalent:@""] retain];
			[item setRepresentedObject:currItem];
			[item setTarget:self];
			[newMenu addItem:item];
			[item release];
			//[newMenu addItem:[[AHMenuItem alloc] initWithTitle:[currItem itemName] action:@"runApplescript" withObjects:[NSArray arrayWithObject:[currItem itemValue]] keyEquivalent:nil target:self]];
		}
		if([[currItem itemAction] isEqualTo:@"Seperator"])
		{
			[newMenu addItem:[[NSMenuItem separatorItem] retain]];
		}
		if([[currItem itemAction] isEqualTo:@"Submenu"])
		{
			[newMenu addItemWithTitle:[currItem itemName] action:nil keyEquivalent:@""];
			[newMenu setSubmenu:[self buildMenu:[currItem returnChildren]] forItem:[newMenu itemWithTitle:[currItem itemName]]];
		}
		[currItem release];
	}
	[newMenu retain];
	return newMenu;	
}

-(void)click:(id)sender
{
	Node * selectedItem = [sender representedObject];
	if([[selectedItem itemAction] isEqualToString:@"Applescript"])
	{
		[self runApplescript:[selectedItem itemValue]];
	}
	else
	{
		NSLog(@"return itms prefs are ", [selectedItem returnItemPreferences]);
		[self runKeystoke:[selectedItem itemValue] withPreferences:[selectedItem returnItemPreferences] inApp:[[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:[selectedItem parentID]]];
	}
}

-(void)runApplescript:(NSString*)inputScript
{
	NSAppleScript * theScript = [[NSAppleScript alloc] initWithSource:inputScript];
	
	NSDictionary * errorDict = [NSDictionary dictionary];
	NSString * errorMessage = [NSString string];
	
	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
	
	NSAppleEventDescriptor * returnDescriptor=[theScript executeAndReturnError: &errorDict];
    [theScript release];
	
	if([returnDescriptor descriptorType]) {
		//	The execution succeeded
    } else {
		errorMessage = [errorDict objectForKey: @"NSAppleScriptErrorMessage"];
		NSLog(errorMessage);
	}
}
-(void)runKeystoke:(NSString*)inputKey withPreferences:(NSDictionary*)prefs inApp:(NSString*)app
{
	NSLog(@"input key is %@", inputKey);
	NSLog(@"prefs are: ", prefs);
	NSString * appPath = app;
	NSArray * modifiers = [prefs objectForKey:@"modifier"];
	NSLog(@"mods are: %@", modifiers);
	NSString * mod;//[prefs objectForKey:@"modifier"];
	if([modifiers count] == 1)
		mod = [modifiers objectAtIndex:0];
	else if([modifiers count] > 1)
	{
		int i = 0;
		mod = @"{";
		for(id currItem in modifiers)
		{
			NSLog(@"current mod = %@", currItem);
			if([currItem isEqualToString:@"control"])
			   mod = [mod stringByAppendingString:@"control down"];
			
			if([currItem isEqualToString:@"alternate"])
			   mod = [mod stringByAppendingString:@"alternate down"];
			
			if([currItem isEqualToString:@"shift"])
			   mod = [mod stringByAppendingString:@"shift down"];
			
			if([currItem isEqualToString:@"command"])
			   mod = [mod stringByAppendingString:@"command down"];
				
			if(i != ([modifiers count]-1))
				mod = [mod stringByAppendingString:@", "];
			i++;
		}
		mod = [mod stringByAppendingString:@"}"];
	}
	else
		mod = @"command down";
	
	NSLog(@"mod string: %@", mod);
	//if([mod isEqualTo:@"Command"]) mod = @"command down";
	NSString * source = [NSString stringWithFormat:@"activate application \"%@\" \n tell application \"System Events\" \n tell process \"%@\" \n delay 0.2 \n keystroke \"%@\" using %@ \n end tell \n end tell", appPath, appPath, [inputKey lowercaseString], mod, nil];
	[self runApplescript:source];
}
			 
-(void)showAbout
{
	[NSApp activateIgnoringOtherApps:YES];
	[NSApp orderFrontStandardAboutPanel:nil];
}
			 
-(void)showSite
{
	[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.mettamedia.com"]];
}
			 
- (NSImage *)invertImage: (NSImage *)image
{
	NSBitmapImageRep *existingImage = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
	RGBAPixel *pixels = (RGBAPixel *)[existingImage bitmapData];  // -bitmapData returns a void*, not an NSData object ;-)
	
	int row,column, widthInPixels = [existingImage pixelsWide], heightInPixels = [existingImage pixelsHigh];
	
	for (row = 0; row < heightInPixels; row++)
	{
		for (column = 0; column < widthInPixels; column++)
		{
			RGBAPixel *thisPixel = (RGBAPixel *) &(pixels[((widthInPixels * row) + column)]);
			thisPixel->redByte = (255 - thisPixel->redByte);
			thisPixel->greenByte = (255 - thisPixel->greenByte);
			thisPixel->blueByte = (255 - thisPixel->blueByte);
			// We're not going to invert the alpha...
		}
	}
	
	return [[NSImage alloc] initWithData:[existingImage TIFFRepresentation]];
}
@end
